#include "../Thread.h"
using namespace yhaida;

//就是这些名称具有internal链接属性，
//这和声明为static的全局名称的链接属性是相同的，
//即名称的作用域被限制在当前文件中，
//无法通过在另外的文件中使用extern声明来进行链接。

namespace
{
    void afterFork()
    {
        CurrentThread::currend_tid = static_cast<pid_t>(syscall(SYS_gettid));
        CurrentThread::currend_thread_name = "main";
    }

    class ThreadNameInitializer
    {
    public:
        ThreadNameInitializer()
        {
            CurrentThread::currend_thread_name = "main";
            //如果线程中使用了fork()，添加一些回调函数
            pthread_atfork(NULL, NULL, &afterFork);
        }
    };
    //只是起到初始化的作用
    ThreadNameInitializer init;
}

namespace
{
    struct ThreadData
    {
        typedef yhaida::Thread::ThreadFunc ThreadFunc;
        ThreadFunc _func;
        std::string _name;
        std::weak_ptr<pid_t> _wkTid;

        ThreadData(const ThreadFunc func,
                   const std::string &name,
                   const std::shared_ptr<pid_t> &tid)
            : _func(std::move(func)),
              _name(name),
              _wkTid(tid)
        {
        }

        void run()
        {
            //获取该线程真实的tid，必须在pthread_create之后
            pid_t tid = CurrentThread::tid();
            //指向tid的share指针+1，sum=2
            std::shared_ptr<pid_t> ptid = _wkTid.lock();
            if (ptid)
            {
                *ptid = tid;
                ////指向tid的share指针-1，sum=1
                ptid.reset();
            }
            if (!_name.empty()) //不是初始化那个空的name的话
            {
                CurrentThread::currend_thread_name = _name.c_str();
            }
            //把参数arg2作为调用进程的经常名字。
            prctl(PR_SET_NAME, CurrentThread::currend_thread_name);

            //运行线程的函数
            try
            {
                _func();
                CurrentThread::currend_thread_name = "finished";
            }
            catch (const std::exception &ex)
            {
                CurrentThread::currend_thread_name = "crashed";
                fprintf(stderr, "exception caught in Thread %s\n", _name.c_str());
                fprintf(stderr, "reason: %s\n", ex.what());
                abort();
            }
            catch (...)
            {
                CurrentThread::currend_thread_name = "crashed";
                fprintf(stderr, "unknown exception caught in Thread %s\n", _name.c_str());
                throw; // rethrow
            }
        }
    };


    void *startThread(void *obj)
    {
        std::shared_ptr<ThreadData> data(static_cast<ThreadData *>(obj));
        // ThreadData *data = static_cast<ThreadData *>(obj);
        data->run();
        // delete data;
        // data = NULL;
        return NULL;
    }
}

AtomicInt32 Thread::_numCreated;
//初始化
Thread::Thread(const ThreadFunc func, const std::string name)
    : _started(false),
      _joined(false),
      _threadId(0),
      _tid(new pid_t(0)), //注意tid是share指针
      _func(std::move(func)),
      _name(std::move(name))

{
    //总的线程数+1
    _numCreated.increment();
}
Thread::~Thread()
{
    //析构的时候要线程运行同时没有join
    if (_started && !_joined)
    {
        pthread_detach(_threadId);
    }
}
// create 线程 或获取线程tid
void Thread::start()
{
    assert(!_started);

    _started = true;
    //新建线程的data  // 如果用了下面的共享指针就犯了一个错误，两个share指针都对raw指针share这是不对！！
    // std::shared_ptr<ThreadData> data(new ThreadData(_func, _name, _tid));
    
    ThreadData* data = new ThreadData(_func,_name,_tid);//传入数据是指针！
    if (pthread_create(&_threadId, NULL, &startThread, data))
    {
        //出错
        _started = false;
        delete data;
        data = NULL;
        abort();
    }
    
}
void Thread::join()
{
    if (_started && !_joined)
    {
        _joined = true;
        pthread_join(_threadId, NULL);
    }
    else
    {
        abort();
    }
}
